"""
请求模块
作用：请求网址，返回网页响应
参数：
    url:网址
    logger:特指loguru的logger，记录日志用
    proxyAndHeaders:接受一个字典，
        字典的key为"headers"和"proxies"或者其中之一
    params:接受一个字典，是url的查询参数
返回：
    ok：判断请求是否成功，True为成功
    resp：网页的response，ok为False时返回空字符串
"""

from random import choice
from time import sleep
from functools import lru_cache

import httpx
from loguru import logger

userAgents = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39'
    ]

def proxies_headers(haveProxy = True,port = 7890):
    '''
    返回代理和请求头
    如果haveProxy为False，则只返回请求头 默认是True
    '''
    headers = {'user-agent':choice(userAgents)}
    if haveProxy:
        proxy = f'127.0.0.1:{port}'
        proxies = {
            "http://":f"http://{proxy}",
            "https://":f"http://{proxy}"
        }
        return {'proxies':proxies,'headers':headers}
    return {'headers':headers}



#@lru_cache(maxsize=512)
def get_html(url,logger=logger,haveProxy = True,port = 10809,params = None):
    '''
    获取网页返回
    参数：
        logger:loguru的logger对象，用于记录log
        proxyAndHeaders:传入请求头和代理，是一个字典。可以调用proxies_headers函数，此函数直接返回
            一个符合要求的结果
        params:跟在url后的query
    返回两个参数：
        ok：代表请求是否成功
        resp：代表请求的响应
    '''
    proxyAndHeaders=proxies_headers(haveProxy=haveProxy,port=port)
    try:
        resp = httpx.get(
            url,
            **proxyAndHeaders,
            params = params,
            timeout=15,
            follow_redirects=True,          # 跟随重定向
        )
    except httpx.ConnectTimeout:
        logger.error(f'超时:{url}')
        return False,''
    except :
        logger.error(f'代理可能有问题:{url}')
        return False,'' 
    
    if resp.status_code == 200:
        logger.info(f"{resp.url} 完成")
        return True,resp
    
    if resp.status_code == 404:
        logger.error(f'404无法访问，url：{resp.url}')
        return True,404
    if resp.status_code == 500:
        logger.error(f'500服务器错误，url：{resp.url}')
        return True,500
    logger.error(f'{resp.url} 被拒绝，状态码:{resp.status_code}')
    return False,resp
    

def get_resp(url,logger=logger,port=10809,haveProxy=True):
    """
    懒得每次写这么多行，直接写个函数循环算了吧
    get_html获取网页，当ok为False时，循环请求，直到ok为True
    当然这个函数有些呆，只在非常确定请求的网页不会或很少出
    幺蛾子时才好用
    """
    ok,resp = get_html(url,logger,port=port,haveProxy=haveProxy)
    while not ok:
        sleep(2)
        ok,resp = get_html(url,logger,port=port,haveProxy=haveProxy)
    return resp



if __name__ == '__main__':
    pass